home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / maestro / source / vcrdub / vcrdub.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-15  |  56.7 KB  |  1,966 lines

  1. /*
  2.  * Copyright (c) 1990, 1991, 1992 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and 
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that (i) the above copyright notices and this permission notice appear in
  7.  * all copies of the software and related documentation, and (ii) the name
  8.  * Stanford may not be used in any advertising or publicity relating to
  9.  * the software without the specific, prior written permission of
  10.  * Stanford.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  15.  *
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  17.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
  18.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT
  19.  * ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY,
  20.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21.  * SOFTWARE.
  22.  */
  23.  
  24. /* $Header: /Source/Media/collab/vcrDub/RCS/vcrDub.c,v 0.24 92/09/08 14:33:38 drapeau Exp $ */
  25. /* $Log:    vcrDub.c,v $
  26.  * Revision 0.24  92/09/08  14:33:38  drapeau
  27.  * Fixed errors in the way edit lists are opened and saved, especially when
  28.  * dealing with the "label" field of an edit.  Proper care is now taken to
  29.  * allocating the correct amount of space for the label, to avoid string
  30.  * length errors.
  31.  * 
  32.  * Revision 0.23  92/09/04  17:10:51  drapeau
  33.  * Modified ConvertToTime() and ConvertToAddress() to eliminate calculations
  34.  * based on NTSC-specific frame rates.  The calculations now use the defined
  35.  * constant "FrameRate", which can be set at compile time.
  36.  * Also, minor reformatting of the code to comply with coding standards.
  37.  * Also, removed offset of 25 frames in DubThisEdit(); this offset should
  38.  * really be done in the specific device driver, as frame drift will vary from
  39.  * device to device.
  40.  * Also, commented DubThisEdit() to better explain the dubbing process between
  41.  * source and edit decks, and replaced NTSC-specific references with the
  42.  * defined constant "FrameRate".
  43.  * In main(), used xv_set_rect() to set location and placement of the dub
  44.  * setup window, instead of using the less reliable "XV_X" and "XV_Y"
  45.  * attributes.
  46.  * 
  47.  * Revision 0.22  92/05/14  17:36:47  drapeau
  48.  * Made several changes:
  49.  * * Removed code that checks for tape identifiers in the header.  This
  50.  *   feature turned out to be too cumbersome, time-consuming, and unreliable.
  51.  * * Added code to support the new Info panel (showing, removing, etc.).
  52.  * * Formatting changes to the code to conform to coding standards.
  53.  * 
  54.  * Revision 0.21  92/01/09  18:17:37  drapeau
  55.  * Slight modifications to make code ANSI-compliant.
  56.  * 
  57.  * Revision 0.20  91/10/10  11:58:46  lim
  58.  * Corrected tempLabel in OpenHandler(). 
  59.  * Added 8 bytes more.
  60.  * 
  61.  * Revision 0.19  91/09/29  16:19:07  lim
  62.  * Moved DisplayChoice to videoObjects.c
  63.  * 
  64.  * Revision 0.18  91/09/24  22:18:26  lim
  65.  * Changed 'DubEdit' to 'vcrDub' everywhere.
  66.  * 
  67.  * Revision 0.17  91/09/02  14:40:35  lim
  68.  * Fixed savehandler. Header is 20 char long!
  69.  * 
  70.  * Revision 0.16  91/08/28  12:44:22  lim
  71.  * SSet canvas height to 1800 pixels (paint window).
  72.  * 
  73.  * Revision 0.15  91/08/27  10:49:25  lim
  74.  * notSaved set when deleting edit too.
  75.  * 
  76.  * Revision 0.14  91/08/25  16:24:30  lim
  77.  * 1. Implemented '-d' option in command line, to indicate whether
  78.  * user wants to see diagnostic messages on stderr or not.
  79.  * 2. File reading and writing has been modified to fit the new format
  80.  * of VCR Edit documents.
  81.  * 3. Generalized CopyMergeEdit by taking in second parameter denoting
  82.  * the index to the srcEditMergeEdit array. Used to take the index to
  83.  * be srcEditSel.
  84.  * 4. Merge edits are not disposed when an edit in the canvas is deleted,
  85.  * because otherwise the source edit list does not have a record of
  86.  * what the merged edits contained once the merged edit on the canvas is
  87.  * deleted.
  88.  * 
  89.  * Revision 0.13  91/08/20  14:55:02  lim
  90.  * Corrected DubQuit()'s error message checking.
  91.  * 
  92.  * Revision 0.12  91/08/20  09:57:38  lim
  93.  * Fixed EditAdd() for single edits.
  94.  * 
  95.  * Revision 0.11  91/08/19  17:10:32  lim
  96.  * Fixed adding merged edit from edit list.
  97.  * 
  98.  * Revision 0.10  91/08/19  16:22:16  lim
  99.  * Initial revision.
  100.  * This version only supports NEC players.
  101.  *  */
  102. static char rcsid[] = "$Header: /Source/Media/collab/vcrDub/RCS/vcrDub.c,v 0.24 92/09/08 14:33:38 drapeau Exp $";
  103.  
  104. #include "vcrDub.h"
  105.  
  106. /* Video stuff */
  107. VideoObject* playVideo;
  108. VideoObject* recVideo;
  109.  
  110.  
  111. vcrDub_window1_objects*        vcrDub_window1;                /* Xview stuff */
  112. vcrDub_dubSetupWindow_objects*    vcrDub_dubSetupWindow;
  113. vcrDub_infoPopup_objects*    vcrDub_infoPopup;
  114. enum Boolean            hitQuit;                /* Flag to denote if 'Quit' button is hit */
  115.  
  116. /* Command line variables */
  117. char* startFilename;                                    /* Name of file in command line */
  118. Xv_font* font;                                /* Font for scroll list */
  119.     
  120. /* Edit list stuff */
  121. int srcEditSel;                                /* Current edit list selection */
  122. int origLines;                                /* Number of lines in source edit list */
  123. int notSaved;                                /* Set when edit manipulations are not saved */
  124. int repeat;                                /* To see if this is a repeat call - XView bug */
  125. char srcEditLabel[MaxListSize][MaxLabelSize+1];                /* Array of srcEdit labels */
  126. int srcEditDur[MaxListSize];                        /* Array of srcEdit durations */
  127. char srcEditStart[MaxListSize][12];                    /* Array of srcEdit start times  */
  128. char srcEditEnd[MaxListSize][12];                    /* Array of srcEdit end times */
  129. int srcEditSpeed[MaxListSize];                        /* Array of srcEdit speed settings */
  130. int srcEditAudio[MaxListSize];                        /* Array of srcEdit audio settings */
  131. MergeEdit* srcEditMergeEdit[MaxListSize];                /* Array of subsequent edits in a merged edit */
  132. enum Boolean srcEditAudioDub[MaxListSize];                /* Array of srcEdit audio dub settings 
  133.                                        - initialized to Yes */
  134.  
  135. /* Canvas stuff */
  136. CanvasData* editCanvas;                            /* Pointer to editCanvas data */
  137. Pixmap audioImage;                            /* Image to draw when audio dubbing is on */
  138. static Xv_singlecolor myColors[] = 
  139. {
  140.   {214, 214, 214},                            /* Grey84 */
  141.   {235, 235, 235},                            /* Grey92 */
  142.   {166, 166, 166},                            /* Grey65 */
  143.   {255, 255, 255},                            /* White */
  144.   {255, 0, 0},                                /* Red */
  145.   {235, 235, 235},                            /* Unused1 */
  146.   {211, 211, 211},                            /* Unused2 */
  147.   {0, 0, 0},                                /* Black */
  148. }
  149. ;
  150.  
  151. /* Video settings */
  152. char tapeCode[MaxNameLength];                        /* Tape header found in edit list file */
  153. int dubbing;                                /* Flag to indicate dubbing */
  154.  
  155. enum Boolean diagMode = No;                        /* Whether to print diagnostic messages */
  156.  
  157. /*
  158.  * This function parses the command line and retrieves all the known options and their arguments.
  159.  * Currently, the two options are hostname and portnumber.
  160.  * After parsing the options, the variable optind will point to the start of those non-option arguments.  
  161.  * In this case, it will be the filename to be loaded.  At present, only one filename will be handled.  So if
  162.  * there are multiple filenames typed, the last one will be loaded.
  163.  */
  164. void CheckOptions(argc, argv)
  165.      int     argc;
  166.      char     **argv;
  167. {
  168.   int optionChar;  
  169.   int option_index = 0;
  170.   static struct option long_options[] =
  171.   {
  172.     {"diagnostics", 0, 0, 'd'},
  173.     {0, 0, 0, 0}
  174.   };
  175.  
  176.   while (1)                                /* Start parsing all known options */
  177.   {
  178.     optionChar = getopt_long_only (argc, argv, "d:",
  179.                   long_options, &option_index);
  180.     if (optionChar == EOF)                        /* Done with all known options */
  181.     {
  182.       break;
  183.     }
  184.     switch (optionChar)                            /* Modified : No host or port options */
  185.     {                                    /* Dub is not used with PortManager/TimeLine */
  186.      case 'd':
  187.       diagMode = Yes;
  188.       break;
  189.      default:
  190.       break;
  191.     }
  192.   }
  193.   if (optind < argc)                            /* Check if a filename has been specified */
  194.   {
  195.     startFilename = (char *) malloc (256);
  196.     strcpy (startFilename, argv[optind]);
  197.   }
  198. }
  199.  
  200.  
  201.  
  202. /* Convert time to address in frames */
  203. int
  204.   ConvertToAddress(time)
  205. char time[12];
  206. {
  207.   int address;
  208.   int hr;
  209.   int min;
  210.   int sec;
  211.   int frame;
  212.   
  213.   sscanf(time, "%d:%d:%d:%d", &hr, &min, &sec, &frame);
  214.   address = FrameRate * (hr*3600 + min*60 + sec) + frame;
  215.   return address;
  216. }
  217.  
  218.  
  219. /* Convert address in frames to time */
  220. void
  221.   ConvertToTime(hr, min, sec, frame, address)
  222. int* hr;
  223. int* min;
  224. int* sec;
  225. int* frame;
  226. int  address;
  227. {
  228.   int    framesPerHour;
  229.   int    framesPerMinute;
  230.   int    framesPerSecond;
  231.   
  232.   framesPerHour = 3600 * FrameRate;                    /* 3600 = seconds per hour */
  233.   framesPerMinute = 60 * FrameRate;
  234.   framesPerSecond = FrameRate;
  235.   
  236.   *hr = address / framesPerHour;
  237.   *min = (address % framesPerHour) / framesPerMinute;
  238.   *sec = ((address % framesPerHour) % framesPerMinute) / framesPerSecond;
  239.   *frame = ((address % framesPerHour) % framesPerMinute) % framesPerSecond;
  240.   
  241. }
  242.  
  243.  
  244.  
  245. /* Set buttons for edit operations active */
  246. void
  247.   EditOpActive(audioDubOn)
  248. enum Boolean audioDubOn;
  249. {
  250.   xv_set(vcrDub_window1->dubDelButton, PANEL_INACTIVE, FALSE, NULL);
  251.   xv_set(vcrDub_window1->dubAudioStg, PANEL_INACTIVE, FALSE, NULL);
  252.   xv_set(vcrDub_window1->dubAudioStg, PANEL_VALUE, (int) audioDubOn, NULL);
  253. }  
  254.  
  255.  
  256. /* Set buttons for edit operations inactive */
  257. void
  258.   EditOpInactive()
  259. {
  260.   xv_set(vcrDub_window1->dubDelButton, PANEL_INACTIVE, TRUE, NULL);
  261.   xv_set(vcrDub_window1->dubAudioStg, PANEL_INACTIVE, TRUE, NULL);
  262.   xv_set(vcrDub_window1->dubAudioStg, PANEL_VALUE, 1, NULL);
  263. }  
  264.  
  265.  
  266.  
  267.  
  268. /* Displays edit list */
  269. void
  270.   DisplayEditList(oldlines)
  271. int oldlines;
  272. {
  273.   int i;
  274.   char listEntry[70];
  275.   
  276.   xv_set(vcrDub_window1->dubAddButton, PANEL_INACTIVE, TRUE, NULL);
  277.   if (srcEditSel >= 0)
  278.     xv_set(vcrDub_window1->dubScrollList, PANEL_LIST_SELECT, srcEditSel, FALSE, NULL);
  279.   
  280.   srcEditSel = -1;
  281.   
  282.   xv_set(vcrDub_window1->dubScrollList,                /* To prevent blinking, set XV_SHOW false */
  283.      XV_SHOW, FALSE,
  284.      NULL);
  285.   
  286.   for (i=0; i<oldlines; i++)                        /* Replace the old string by the new one */
  287.   {
  288.     sprintf(listEntry, "%5d.  %-26.22s%3d", i+1, 
  289.         srcEditLabel[i], srcEditDur[i]);
  290.     xv_set (vcrDub_window1->dubScrollList,
  291.         PANEL_LIST_STRING, i, listEntry,
  292.         PANEL_LIST_FONT, i, font,
  293.         NULL);
  294.   }
  295.   
  296.   if (oldlines < origLines)                        /* Insert the additional new strings */
  297.     for (i=oldlines; i<origLines; i++) 
  298.     {
  299.       sprintf(listEntry, "%5d.  %-26.22s%3d", i+1, 
  300.           srcEditLabel[i], srcEditDur[i]);
  301.       xv_set (vcrDub_window1->dubScrollList,
  302.           PANEL_LIST_INSERT, i,
  303.           PANEL_LIST_STRING, i, listEntry,
  304.           PANEL_LIST_FONT, i, font,
  305.           NULL);
  306.     }
  307.   
  308.   else for (i=oldlines-1; i> origLines-1; i--)                /* delete all additional old entries in the edit list */
  309.     xv_set(vcrDub_window1->dubScrollList,
  310.        PANEL_LIST_DELETE, i,
  311.        NULL);
  312.   
  313.   xv_set(vcrDub_window1->dubScrollList,                /* Reshow the scrolling list */
  314.      XV_SHOW, TRUE,
  315.      NULL);  
  316. }
  317.  
  318.  
  319. /*
  320.  * Menu handler for `DocMenu (Open)'.
  321.  */
  322. Menu_item
  323.   DubFileOpen(item, op)
  324. Menu_item    item;
  325. Menu_generate    op;
  326. {
  327.   int result;
  328.   
  329.   if (op == MENU_NOTIFY)
  330.   {
  331.     if (notSaved)                            /* New edit manipulations made */
  332.     {
  333.       result = DisplayChoice("The edit list manipulations will be lost",
  334.                  "Go ahead and load another file?", "No", "Yes");
  335.       if (result == NOTICE_YES)
  336.     return item;
  337.     }
  338.     
  339.     Browse(NULL, BrowseOpen, NULL, "#VCR Edit Document#", "vcrDub");
  340.   }
  341.   
  342.   return item;
  343. }
  344.  
  345.  
  346. EditLink*
  347.   GetEdit(which)
  348. int which;                                /* from 0 to n-1 */
  349. {
  350.   int i;
  351.   EditLink* current;
  352.   
  353.   current = editCanvas->listHead;
  354.   
  355.   for (i = 0; ((i < which) && current); i++)
  356.     current = current->nextEdit;
  357.   
  358.   if (i == which)
  359.     return current;
  360.   else
  361.     return NULL;
  362. }
  363.  
  364.  
  365.  
  366. /* Frees up the merged list */
  367. void
  368.   DisposeMergedList(head)
  369. MergeEdit* head;
  370. {
  371.   MergeEdit* p;
  372.   MergeEdit* q;
  373.   
  374.   for (p = head; p != NULL; p = q)
  375.   {
  376.     q = p->nextMergeEdit;
  377.     free(p);
  378.   }
  379. }
  380.  
  381.  
  382. /* Frees up the linked list */
  383. void
  384.   DisposeLinkedList(head)
  385. EditLink* head;
  386. {
  387.   EditLink* p;
  388.   EditLink* q;
  389.   
  390.   for (p = head; p != NULL; p = q)
  391.   {
  392.     q = p->nextEdit;
  393.     if (p->mergeList)
  394.       DisposeMergedList(p->mergeList);
  395.     free(p);
  396.   }
  397. }
  398.  
  399.  
  400. /* Sets up the linked list of edits in the canvas */
  401. void
  402.   SetUpLinkedList(head, tail)
  403. EditLink** head;
  404. EditLink** tail;
  405. {
  406.   int i;
  407.   EditLink* tmp;
  408.   EditLink* prev;
  409.   
  410.   if (*head)                                /* Dispose of old list */
  411.     DisposeLinkedList(*head);
  412.   
  413.   (*head) = (EditLink*) malloc(sizeof(EditLink));            /* Initialize head of list */
  414.   (*head)->nextEdit = NULL;
  415.   (*head)->prevEdit = NULL;
  416.   (*head)->origNum = 0;
  417.   (*head)->audioDub = Yes;
  418.   (*head)->mergeList = NULL; 
  419.   (*head)->sMode = Unselected; 
  420.   prev = (*head);
  421.   
  422.   for (i=1; i < origLines; i++)
  423.   {
  424.     tmp = (EditLink*) malloc(sizeof(EditLink));
  425.     tmp->nextEdit = NULL;
  426.     tmp->prevEdit = prev;                        /* Points to previous edit */
  427.     tmp->origNum = i;
  428.     tmp->audioDub = Yes;
  429.     tmp->mergeList = NULL; 
  430.     prev->nextEdit = tmp;
  431.     prev->sMode = Unselected; 
  432.     prev = tmp;
  433.   }  
  434.   (*tail) = prev;
  435.   editCanvas->numInLinkedList = origLines;
  436.   return;
  437.   
  438. }
  439.  
  440.  
  441. /* Draws outline of edit, depending on whether selected or not */
  442. void
  443.   DrawOutline(x, y, sel)
  444. int x;
  445. int y;
  446. enum SelectMode sel;
  447. {
  448.   XPoint *points = (XPoint*) malloc (sizeof (XPoint) *3);        /* Array of point coordinates to be passed to  XDrawLines() */
  449.   
  450.   if (sel == Unselected)                        /* Drawing top and left borders */
  451.     XSetForeground(editCanvas->display, editCanvas->gc, editCanvas->pixelTable[White]);
  452.   else
  453.     XSetForeground(editCanvas->display, editCanvas->gc, editCanvas->pixelTable[Black]);
  454.   
  455.   points[0].x = x;
  456.   points[0].y = y+EditHeight;
  457.   points[1].x = x;
  458.   points[1].y = y;
  459.   points[2].x = x+EditWidth;
  460.   points[2].y = y;
  461.   XDrawLines(editCanvas->display, editCanvas->drawable, editCanvas->gc, points, 3, CoordModeOrigin);
  462.   
  463.   
  464.   if (sel == Unselected)                        /* Drawing bottom and right borders */
  465.     XSetForeground(editCanvas->display, editCanvas->gc, editCanvas->pixelTable[Black]);
  466.   else
  467.     XSetForeground(editCanvas->display, editCanvas->gc, editCanvas->pixelTable[White]);
  468.   
  469.   points[0].x = x+EditWidth;
  470.   points[0].y = y;
  471.   points[1].x = x+EditWidth;
  472.   points[1].y = y+EditHeight;
  473.   points[2].x = x;
  474.   points[2].y = y+EditHeight;
  475.   XDrawLines(editCanvas->display, editCanvas->drawable, editCanvas->gc, points, 3, CoordModeOrigin);
  476.   
  477. }
  478.  
  479.  
  480.  
  481. /* Draws each edit.
  482.  * Fill rectangle accordingly.
  483.  * Call function to draw outlines accordingly.
  484.  * Draws audio icon if audio dub is on
  485.  */
  486. void
  487.   DrawEdit(x, y, string, audio, sel)
  488. int x;
  489. int y;
  490. char* string;
  491. enum Boolean audio;
  492. enum SelectMode sel;
  493. {
  494.   if (sel == Unselected)
  495.     XSetForeground(editCanvas->display, editCanvas->gc, editCanvas->pixelTable[Grey92]);
  496.   else 
  497.     XSetForeground(editCanvas->display, editCanvas->gc, editCanvas->pixelTable[Grey65]);
  498.   XFillRectangle(editCanvas->display, editCanvas->drawable, editCanvas->gc, x, y, EditWidth, EditHeight);
  499.   
  500.   XSetForeground(editCanvas->display, editCanvas->gc, editCanvas->pixelTable[Black]);
  501.   XSetBackground(editCanvas->display, editCanvas->gc, editCanvas->pixelTable[Grey92]);
  502.   if (audio == Yes)
  503.     XCopyPlane(editCanvas->display, audioImage, editCanvas->drawable, editCanvas->gc, 
  504.            0, 0, audioBitmap_width, audioBitmap_height, x+AudioXOffset, y+AudioYOffset, 1);
  505.   
  506.   XDrawString(editCanvas->display, editCanvas->drawable, editCanvas->gc, x+LabelXOffset, y+LabelYOffset,
  507.           string, strlen(string));
  508.   DrawOutline(x, y, sel);
  509. }
  510.  
  511.  
  512.  
  513. /* Draws the linked list onto the canvas */
  514. void
  515.   DrawLinkedList(head, renumber)
  516. EditLink* head;
  517. enum Boolean renumber;
  518. {
  519.   int i;
  520.   int y;
  521.   EditLink* current;
  522.   char label[40];
  523.   enum Boolean audioDubOn;
  524.   
  525.   XClearWindow(editCanvas->display, editCanvas->drawable);        /* clear the whole display */
  526.   current = head;
  527.   y = 0;
  528.   
  529.   for (i = 0; current; i++)
  530.   {
  531.     y += (EditGap + EditHeight);
  532.     audioDubOn = current->audioDub;
  533.     if (renumber == Yes)
  534.     {
  535.       current->origNum = i;
  536.       sprintf(label, "%3d. %-23.22s", i+1, srcEditLabel[current->origNum]);
  537.     }
  538.     else
  539.       sprintf(label, "%3d. %-23.22s", current->origNum+1, srcEditLabel[current->origNum]);
  540.     if (current->sMode == Selected)
  541.       DrawEdit(LeftMargin, y, label, audioDubOn, Selected);
  542.     else 
  543.       DrawEdit(LeftMargin, y, label, audioDubOn, Unselected);
  544.     
  545.     current = current->nextEdit;
  546.   }
  547.   
  548. }
  549.  
  550.  
  551.  
  552. /* Opens the edit file and loads into data structures.
  553.  * Displays new canvas.
  554.  * Returns -1 to OpenPanel if the file is of the wrong type.
  555.  * Otherwise returns 0.
  556.  */
  557. int 
  558.   OpenHandler(proposedPath, id)
  559. char* proposedPath;
  560. int id;
  561. {
  562.   int oldlines;
  563.   int i;
  564.   char tempLabel[MaxLabelSize+10];
  565.   char statusMsg[MaxPathLength+20];
  566.   char header[32];
  567.   FILE* fp;
  568.   
  569.   fp = fopen(proposedPath, "r");                    /* Load file into array */
  570.   fgets(header, 20, fp);
  571.   if (strcmp(header, "#VCR Edit Document#") != 0) 
  572.   {
  573.     DisplayError("This is not a VCR edit file", " ");
  574.     fclose(fp);
  575.     return -1;                                /* Returns error to OpenPanel */
  576.   }
  577.   
  578.   oldlines = origLines;
  579.   
  580.   fscanf(fp, "%*s%*s%s\n", tapeCode);
  581.   
  582.   sprintf(statusMsg, "Current document: %s", proposedPath);        /* Set message on window */
  583.   xv_set(vcrDub_window1->dubStatusMsg, PANEL_LABEL_STRING, 
  584.      statusMsg, NULL); 
  585.   
  586.   fscanf(fp, "%*s%*s%*s%d", &origLines);  
  587.   if (!origLines)                            /* There are no edits, return */
  588.   {
  589.     DisplayError("There are no edits in this file", 
  590.          "Please choose another one");
  591.     return -1;
  592.   }
  593.   
  594.   for (i=0; i<origLines; i++) 
  595.   {
  596.     fscanf(fp, "%*s%*s%*d");
  597.     fscanf(fp, "%*s%*s%11s\n", srcEditStart[i]);
  598.     fscanf(fp, "%*s%*s%11s\n", srcEditEnd[i]);
  599.     fscanf(fp, "%*s%*s%d\n", &srcEditAudio[i]);
  600.     fscanf(fp, "%*s%*s%*s%d\n", &srcEditSpeed[i]);
  601.     
  602.     if (srcEditSpeed[i])
  603.       srcEditDur[i] = (ConvertToAddress(srcEditEnd[i]) - ConvertToAddress(srcEditStart[i]))/srcEditSpeed[i];
  604.     else
  605.       srcEditDur[i] = 0;
  606.     
  607.     fgets(tempLabel, 32, fp);
  608.     strncpy(srcEditLabel[i], &tempLabel[8], MaxLabelSize);
  609.     if (strcmp(srcEditLabel[i], "\n") == 0)
  610.       strcpy(srcEditLabel[i], "No label\n");
  611.     srcEditAudioDub[i] = Yes;                        /* Defaults to Yes */
  612.     srcEditMergeEdit[i] = NULL;                        
  613.     
  614.     if (strlen(srcEditLabel[i]) < MaxLabelSize)                /* Remove newline character if necessary */
  615.       srcEditLabel[i][strlen(srcEditLabel[i])-1] = '\0';
  616.     if ((strlen(srcEditLabel[i]) == MaxLabelSize) 
  617.     && (srcEditLabel[i][MaxLabelSize-1] == '\n'))
  618.       srcEditLabel[i][MaxLabelSize-1] = '\0';
  619.   }
  620.   fclose(fp);
  621.   
  622.   editCanvas->numMerged = 0;
  623.   editCanvas->numInMergedLists = 0;
  624.   editCanvas->firstSelected = -1;
  625.   notSaved = 0;
  626.   
  627.   DisplayEditList(oldlines);
  628.   EditOpInactive();
  629.   SetUpLinkedList(&(editCanvas->listHead),                /* Set up linked list of these edits */
  630.           &(editCanvas->listTail));                
  631.   DrawLinkedList(editCanvas->listHead, No);                /* Draw linked list on canvas */
  632.   return 0;
  633.   
  634. }                                    /* end function OpenHandler */
  635.  
  636.  
  637. /* Loads edit list from linked list.
  638.  * Calls DisplayEditList().
  639.  */
  640. void
  641.   LoadEditList(head)
  642. EditLink* head;
  643. {
  644.   int i;
  645.   int oldLines;
  646.   EditLink* current;
  647.   char tmpEditLabel[MaxListSize][MaxLabelSize+1];            /* Array of tmpEdit labels */
  648.   int tmpEditDur[MaxListSize];                        /* Array of tmpEdit durations */
  649.   char tmpEditStart[MaxListSize][12];                    /* Array of tmpEdit start times  */
  650.   char tmpEditEnd[MaxListSize][12];                    /* Array of tmpEdit end times */
  651.   int tmpEditSpeed[MaxListSize];                    /* Array of tmpEdit speed settings */
  652.   int tmpEditAudio[MaxListSize];                    /* Array of tmpEdit audio settings */
  653.   MergeEdit* tmpEditMergeEdit[MaxListSize];                /* Array of subseq edits for a merged edit */
  654.   
  655.   current = head;
  656.   
  657.   for (i = 0; i< origLines; i++)                    /* Place old values into temporary arrays */
  658.   {
  659.     strcpy(tmpEditLabel[i], srcEditLabel[i]);
  660.     strcpy(tmpEditStart[i], srcEditStart[i]);
  661.     strcpy(tmpEditEnd[i], srcEditEnd[i]);
  662.     tmpEditDur[i] = srcEditDur[i];
  663.     tmpEditSpeed[i] = srcEditSpeed[i];
  664.     tmpEditAudio[i] = srcEditAudio[i];
  665.     tmpEditMergeEdit[i] = srcEditMergeEdit[i];
  666.   }
  667.   
  668.   for (i = 0; i<editCanvas->numInLinkedList; i++)            /* Put linked list edits into source arrays */
  669.   {
  670.     strcpy(srcEditLabel[i], tmpEditLabel[current->origNum]);
  671.     strcpy(srcEditStart[i], tmpEditStart[current->origNum]);
  672.     strcpy(srcEditEnd[i], tmpEditEnd[current->origNum]);
  673.     srcEditDur[i] = tmpEditDur[current->origNum];
  674.     srcEditSpeed[i] = tmpEditSpeed[current->origNum];
  675.     srcEditAudio[i] = tmpEditAudio[current->origNum];
  676.     srcEditAudioDub[i] = current->audioDub;
  677.     srcEditMergeEdit[i] = current->mergeList;                
  678.     current = current->nextEdit;
  679.   }
  680.   oldLines = origLines;                            
  681.   origLines = editCanvas->numInLinkedList;                /* Update origLines */
  682.   
  683.   DisplayEditList(oldLines);
  684.   
  685. }  
  686.  
  687.  
  688.  
  689. /*
  690.  * Menu handler for `DocMenu (Save)'.
  691.  */
  692. Menu_item
  693.   DubFileSave(item, op)
  694. Menu_item    item;
  695. Menu_generate    op;
  696. {
  697.   if (op == MENU_NOTIFY)
  698.     Browse(NULL, BrowseSave, NULL, "#VCR Edit Document#", "vcrDub");
  699.   
  700.   return item;
  701. }
  702.  
  703.  
  704. /* Saves into a file from edit list. 
  705.  * Called only after dubbing. 
  706.  */
  707. void
  708.   SaveFromEditList(fp)
  709. FILE* fp;
  710. {
  711.   int i;
  712.   
  713.   for (i = 0; i < origLines; i++)
  714.   {
  715.     fprintf(fp, "#Edit Number:\t%d\n", i+1);
  716.     fprintf(fp, "#Start Address:\t%.11s\n", srcEditStart[i]);
  717.     fprintf(fp, "#End Address:\t%.11s\n", srcEditEnd[i]);
  718.     fprintf(fp, "#Audio Setting:\t%d\n", srcEditAudio[i]);
  719.     fprintf(fp, "#Speed in frames/second:\t%d\n", srcEditSpeed[i]);
  720.     fprintf(fp, "#Label:\t%s\n\n", srcEditLabel[i]);
  721.   }
  722. }    
  723.  
  724.  
  725.  
  726. /* Saves the file into proposed path.
  727.  * Loads the new file into the edit list.
  728.  * Returns error to OpenPanel if there is already a file of the same name that the user does
  729.  * not want to overwrite.
  730.  * Otherwise, returns 0.
  731.  */
  732. int
  733.   SaveHandler(proposedPath, id)
  734. char* proposedPath;
  735. int id;
  736. {
  737.   FILE* fp;
  738.   struct stat stbuf;
  739.   EditLink* current;
  740.   MergeEdit* currentMerge;
  741.   char header[21];
  742.   char buf[30];
  743.   char diagMsg[30];
  744.   int result;
  745.   int editNum;
  746.   int i;
  747.   
  748.   if (stat(proposedPath, &stbuf) == 0)                    /* check if file existed previously ...
  749.                                        ... and if it is a vcr edit file */
  750.   {
  751.     fp = fopen(proposedPath, "r");
  752.     fgets(header, 20, fp);
  753.     fclose(fp);
  754.     
  755.     if (strcmp(header, "#VCR Edit Document#") != 0) 
  756.       sprintf(buf, "This file is not a vcr edit file.");
  757.     else
  758.       sprintf(buf, "This vcr edit file exists.");
  759.     result = DisplayChoice(buf, "Do you wish to overwrite it?",
  760.                "No", "Yes");
  761.     if (result == NOTICE_YES) 
  762.       return 1;                                /* Returns 1 to openPanel */
  763.   }
  764.   
  765.   fp = fopen(proposedPath, "w");
  766.   fprintf(fp, "#VCR Edit Document#\n");
  767.   fprintf(fp, "#Tape Code:\t%s\n", tapeCode);
  768.   fprintf(fp, "#Number of Edits:\t%d\n\n", (editCanvas->numInLinkedList)+(editCanvas->numInMergedLists)-(editCanvas->numMerged));
  769.   sprintf(diagMsg, "%d + %d - %d = %d\n", (editCanvas->numInLinkedList), (editCanvas->numInMergedLists), 
  770.       (editCanvas->numMerged), (editCanvas->numInLinkedList)+(editCanvas->numInMergedLists)-(editCanvas->numMerged));
  771.   PrintDiagnostics(diagMsg);
  772.   
  773.   if (id)
  774.     SaveFromEditList(fp);
  775.   else 
  776.   {
  777.     current = editCanvas->listHead;
  778.     i = 0;
  779.     while (current)
  780.     {
  781.       editNum = current->origNum;
  782.       currentMerge = current->mergeList;
  783.       
  784.       fprintf(fp, "#Edit Number:\t%d\n", i+1);
  785.       
  786.       if (!currentMerge)                        /* Not merged with other edits */
  787.       {
  788.     fprintf(fp, "#Start Address:\t%.11s\n", srcEditStart[editNum]);
  789.     fprintf(fp, "#End Address:\t%.11s\n", srcEditEnd[editNum]);
  790.     fprintf(fp, "#Audio Setting:\t%d\n", srcEditAudio[editNum]);
  791.     fprintf(fp, "#Speed in frames/second:\t%d\n", srcEditSpeed[editNum]);
  792.     fprintf(fp, "#Label:\t%s\n\n", srcEditLabel[editNum]);
  793.     i++;
  794.       }
  795.       else                                /* Is merged with other edits */
  796.       {
  797.     fprintf(fp, "#Start Address:\t%.11s\n", currentMerge->startAddress);
  798.     fprintf(fp, "#End Address:\t%.11s\n", currentMerge->endAddress);
  799.     fprintf(fp, "#Audio Setting:\t0\n");
  800.     fprintf(fp, "#Speed in frames/second:\t30\n");
  801.     fprintf(fp, "#Label:\t%s\n\n", srcEditLabel[editNum]);
  802.     currentMerge = currentMerge->nextMergeEdit;
  803.     i++;
  804.       }
  805.       
  806.       while (currentMerge)                       
  807.       { 
  808.     fprintf(fp, "#Edit Number:\t%d\n", i+1);
  809.     fprintf(fp, "#Start Address:\t%.11s\n", currentMerge->startAddress);
  810.     fprintf(fp, "#End Address:\t%.11s\n", currentMerge->endAddress);
  811.     fprintf(fp, "#Audio Setting:\t0\n");
  812.     fprintf(fp, "#Speed in frames/second:\t30\n");
  813.     fprintf(fp, "#Label:\tTo merge with above\n\n");
  814.     currentMerge = currentMerge->nextMergeEdit;
  815.     i++;
  816.       }
  817.       current = current->nextEdit;
  818.     }
  819.     LoadEditList(editCanvas->listHead);                    /* Display new edit list */
  820.     DrawLinkedList(editCanvas->listHead, Yes);
  821.   }
  822.   
  823.   fclose (fp);
  824.   
  825.   notSaved = 0;                                /* File has been saved */
  826.   
  827.   return 0;
  828. }
  829.  
  830.  
  831.  
  832. /*
  833.  * Notify callback function for `dubStartButton'.
  834.  * Dubbing requires the edit list be updated.
  835.  */
  836. void
  837.   DubStart(item, event)
  838. Panel_item    item;
  839. Event        *event;
  840. {
  841.   if (!origLines)
  842.   {
  843.     DisplayError("There are no edits in the edit list",
  844.          "Dubbing aborted");
  845.     return;
  846.   }
  847.   
  848.   xv_set(vcrDub_dubSetupWindow->dubSetupWindow, XV_SHOW, TRUE, NULL);
  849.   xv_set(vcrDub_dubSetupWindow->dubSetupWindow, FRAME_CMD_PUSHPIN_IN, TRUE, NULL);
  850. }
  851.  
  852.  
  853. /*
  854.  * Notify callback function for `dubQuitButton'.
  855.  */
  856. void
  857.   DubQuit(item, event)
  858. Panel_item    item;
  859. Event        *event;
  860. {
  861.   int result;
  862.   
  863.   if (playVideo)
  864.     DevStop(playVideo);
  865.   if (recVideo)
  866.     DevStop(recVideo);
  867.   
  868.   if ((notSaved)&&(!hitQuit))                        /* check if unsaved changes exist in canvas */
  869.   {
  870.     result = DisplayChoice("New edit manipulations will be lost.", 
  871.                "Go ahead and quit?",
  872.                "No", "Yes");
  873.     if (result == NOTICE_YES)
  874.       return;
  875.   }
  876.   
  877.   hitQuit = 1;
  878.   
  879.   DisposeLinkedList(editCanvas->listHead);
  880.   xv_destroy_safe(vcrDub_window1->window1);
  881. }
  882.  
  883.  
  884. /* Returns number of items in merged list */
  885. int
  886.   NumInList(list)
  887. MergeEdit* list;
  888. {
  889.   int result;
  890.   
  891.   result = 0;
  892.   while (list)
  893.   {
  894.     result ++;
  895.     list = list->nextMergeEdit;
  896.   }
  897.   return result;
  898. }
  899.  
  900.  
  901. void
  902.   CopyMergeEdits(new, editnum)
  903. MergeEdit** new;
  904. int editnum;                            /* from 0 to n-1 */
  905. {
  906.   MergeEdit* current;
  907.   MergeEdit* prev;
  908.   
  909.   if (srcEditMergeEdit[editnum] == NULL)
  910.     return;
  911.   
  912.   (*new) = (MergeEdit*) malloc(sizeof(MergeEdit));
  913.   strcpy((*new)->startAddress, srcEditMergeEdit[editnum]->startAddress);
  914.   strcpy((*new)->endAddress, srcEditMergeEdit[editnum]->endAddress);
  915.   (*new)->nextMergeEdit = NULL;
  916.   current = srcEditMergeEdit[editnum]->nextMergeEdit;
  917.   prev = (*new);
  918.   
  919.   while (current)
  920.   {
  921.     prev->nextMergeEdit = (MergeEdit*) malloc(sizeof(MergeEdit));
  922.     strcpy(prev->nextMergeEdit->startAddress, current->startAddress);
  923.     strcpy(prev->nextMergeEdit->endAddress, current->endAddress);
  924.     prev->nextMergeEdit->nextMergeEdit = NULL;
  925.     prev = prev->nextMergeEdit;
  926.     current = current->nextMergeEdit;
  927.   }
  928. }
  929.  
  930.  
  931. /*
  932.  * Notify callback function for `dubAddButton'.
  933.  * New edit is put at the tail of the linked list.
  934.  * The list is displayed.
  935.  */
  936. void
  937.   EditAdd(item, event)
  938. Panel_item    item;
  939. Event        *event;
  940. {
  941.   EditLink* newEdit;
  942.   int mergedInThisEdit;
  943.   char label[40];
  944.   char diagMsg[30];
  945.   
  946.   if (srcEditSel < 0)
  947.     return;
  948.   
  949.   newEdit = (EditLink*) malloc(sizeof(EditLink));
  950.   if (editCanvas->listTail)
  951.   {
  952.     editCanvas->listTail->nextEdit = newEdit;
  953.     newEdit->prevEdit = editCanvas->listTail;
  954.   }
  955.   else
  956.   {
  957.     editCanvas->listHead = newEdit;
  958.     newEdit->prevEdit = NULL;
  959.   }
  960.   
  961.   newEdit->nextEdit = NULL;
  962.   newEdit->origNum = srcEditSel;
  963.   newEdit->audioDub = Yes;                        /* Defaults to Yes */
  964.   newEdit->mergeList = NULL;                        /* Initialized to NULL */
  965.   CopyMergeEdits(&newEdit->mergeList, srcEditSel);
  966.   editCanvas->listTail = newEdit;
  967.   editCanvas->numInLinkedList ++;
  968.   mergedInThisEdit = NumInList(newEdit->mergeList);
  969.   if (mergedInThisEdit)
  970.     editCanvas->numMerged ++;
  971.   editCanvas->numInMergedLists += mergedInThisEdit;
  972.   sprintf(diagMsg, "Num in merged list: %d\n", editCanvas->numInMergedLists);
  973.   PrintDiagnostics(diagMsg);
  974.   
  975.   sprintf(label, "%3d. %-23.22s", srcEditSel+1, srcEditLabel[srcEditSel]);
  976.   DrawEdit(LeftMargin, editCanvas->numInLinkedList*(EditGap+EditHeight), label, Yes, Unselected);
  977. }
  978.  
  979.  
  980. /*
  981.  * Notify callback function for `dubScrollList'.
  982.  */
  983. int
  984.   DubSelect(item, string, client_data, op, event)
  985. Panel_item    item;
  986. char        *string;
  987. Xv_opaque    client_data;
  988. Panel_list_op    op;
  989. Event        *event;
  990. {
  991.   int selection;
  992.   
  993.   switch(op) 
  994.   {
  995.    case PANEL_LIST_OP_DESELECT:
  996.     xv_set(vcrDub_window1->dubAddButton, PANEL_INACTIVE, TRUE, NULL);
  997.     srcEditSel = -1;          
  998.     break;
  999.     
  1000.    case PANEL_LIST_OP_SELECT:
  1001.     xv_set(vcrDub_window1->dubAddButton, PANEL_INACTIVE, FALSE, NULL);
  1002.     sscanf(string, "%d", &selection);
  1003.     srcEditSel = selection - 1;
  1004.     break;
  1005.   }
  1006.   return XV_OK;
  1007. }
  1008.  
  1009.  
  1010. /*
  1011.  * Notify callback function for `DubAudioStg'.
  1012.  */
  1013. void
  1014.   SetAudioDub(item, value, event)
  1015. Panel_item    item;
  1016. int        value;
  1017. Event        *event;
  1018. {
  1019.   char string[30];
  1020.   EditLink* current;
  1021.   
  1022.   if (editCanvas->firstSelected)
  1023.     current = GetEdit(editCanvas->firstSelected-1);
  1024.   
  1025.   if (value)
  1026.     current->audioDub = Yes;
  1027.   else
  1028.     current->audioDub = No;
  1029.   
  1030.   sprintf(string, "%3d. %-23.22s", current->origNum+1, srcEditLabel[current->origNum]);
  1031.   DrawEdit(LeftMargin, (editCanvas->firstSelected)*(EditGap+EditHeight),
  1032.        string, current->audioDub, Selected);
  1033. }
  1034.  
  1035.  
  1036.  
  1037. /* Deletes edit from linked list and decrements 
  1038.  * numInLinkedList
  1039.  */
  1040. void
  1041.   EditDelete(toDel)
  1042. EditLink* toDel;
  1043. {
  1044.   char diagMsg[30];
  1045.   
  1046.   if (toDel)
  1047.   {
  1048.     if (toDel->prevEdit)
  1049.       toDel->prevEdit->nextEdit = toDel->nextEdit;
  1050.     else
  1051.       editCanvas->listHead = toDel->nextEdit;
  1052.     
  1053.     if (toDel->nextEdit)
  1054.       toDel->nextEdit->prevEdit = toDel->prevEdit;
  1055.     else
  1056.       editCanvas->listTail = toDel->prevEdit;
  1057.     
  1058.     toDel->nextEdit = NULL;
  1059.     toDel->prevEdit = NULL;    
  1060.     if (toDel->mergeList)
  1061.     {
  1062.       editCanvas->numInMergedLists -= (NumInList(toDel->mergeList));
  1063.       sprintf(diagMsg, "number in merged list :%d\n", editCanvas->numInMergedLists);
  1064.       PrintDiagnostics(diagMsg);
  1065.       editCanvas->numMerged--;
  1066.     }
  1067.     free(toDel);    
  1068.     editCanvas->numInLinkedList--;
  1069.   }
  1070. }
  1071.  
  1072.  
  1073.  
  1074. /*
  1075.  * Notify callback function for `dubMergeButton'.
  1076.  * Creates a new entry in srcEdit arrays. 
  1077.  * Increments origLines.
  1078.  * Deletes selected edits and replaces them by one new edit.
  1079.  * Defaults to audio dub on.
  1080.  * Previously set audio and speed settings will be reset to defaults.
  1081.  * Label must be entered.
  1082.  */
  1083. void
  1084.   EditMerge(item, event)
  1085. Panel_item    item;
  1086. Event        *event;
  1087. {
  1088.   EditLink* mergedEdit;
  1089.   EditLink* current;
  1090.   EditLink* toDel;
  1091.   MergeEdit* newMerge;
  1092.   MergeEdit* tmp;
  1093.   char listEntry[30];
  1094.   char diagMsg[30];
  1095.   
  1096.   current = editCanvas->listHead;                    /* Start from the end */
  1097.   
  1098.   strcpy(srcEditLabel[origLines], 
  1099.      (char*) xv_get(vcrDub_window1->dubMergeLabel, PANEL_VALUE));
  1100.   srcEditSpeed[origLines] = 30;                        /* Defaults to '30' */
  1101.   srcEditAudio[origLines] = 0;                        /* Defaults to 'Stereo' */
  1102.   srcEditAudioDub[origLines] = Yes;
  1103.   srcEditMergeEdit[origLines] = NULL;                    /* Initialized to NULL */
  1104.   strcpy(srcEditStart[origLines], "na");                /* Initialized to 'na' */
  1105.   strcpy(srcEditEnd[origLines], "na");                    /* Initialized to 'na' */
  1106.   
  1107.   while (current)                            /* Go up linked list */
  1108.   {
  1109.     if (current->sMode == Selected)
  1110.     {
  1111.       srcEditDur[origLines] += srcEditDur[current->origNum];
  1112.       sprintf(diagMsg, "duration : %d\n", srcEditDur[origLines]);
  1113.       PrintDiagnostics(diagMsg);
  1114.       toDel = current;
  1115.       
  1116.       if (srcEditMergeEdit[origLines])
  1117.       {
  1118.     tmp = srcEditMergeEdit[origLines];
  1119.     while (tmp->nextMergeEdit)                       
  1120.       tmp = tmp->nextMergeEdit;                    /* tmp points to the last merge edit currently */
  1121.       } 
  1122.       
  1123.       if (current->mergeList)                        /* This is a merged edit */
  1124.       { 
  1125.     if (srcEditMergeEdit[origLines] == NULL)            
  1126.       CopyMergeEdits(&srcEditMergeEdit[origLines], current->origNum);
  1127.     else                                
  1128.       CopyMergeEdits(&tmp->nextMergeEdit, current->origNum);
  1129.       }    
  1130.       else                                /* This is a normal edit */
  1131.       {
  1132.     newMerge = (MergeEdit*) malloc(sizeof(MergeEdit));
  1133.     strcpy(newMerge->startAddress, srcEditStart[current->origNum]);
  1134.     strcpy(newMerge->endAddress, srcEditEnd[current->origNum]);
  1135.     newMerge->nextMergeEdit = NULL;
  1136.     if (srcEditMergeEdit[origLines])
  1137.       tmp->nextMergeEdit = newMerge;
  1138.     else
  1139.       srcEditMergeEdit[origLines] = newMerge;
  1140.       }
  1141.       
  1142.       current = current->nextEdit;
  1143.       EditDelete(toDel);                        /* Delete the edit that was just merged */
  1144.     }
  1145.     else
  1146.       current = current->nextEdit;
  1147.   }
  1148.   editCanvas->firstSelected = -1;                    /* Nothing is selected */
  1149.   
  1150.   mergedEdit = (EditLink*) malloc(sizeof(EditLink));            /* Add new edit to end of the list */
  1151.   if (editCanvas->listTail)
  1152.     editCanvas->listTail->nextEdit = mergedEdit;
  1153.   else
  1154.     editCanvas->listHead = mergedEdit;
  1155.   mergedEdit->nextEdit = NULL;
  1156.   mergedEdit->prevEdit = editCanvas->listTail;
  1157.   mergedEdit->origNum = origLines;
  1158.   mergedEdit->audioDub = Yes;                        /* Defaults to Yes */
  1159.   mergedEdit->mergeList = srcEditMergeEdit[origLines];
  1160.   mergedEdit->sMode = Unselected;
  1161.   editCanvas->listTail = mergedEdit;
  1162.   editCanvas->numInLinkedList ++;
  1163.   editCanvas->numMerged ++;
  1164.   editCanvas->numInMergedLists += (NumInList(mergedEdit->mergeList));
  1165.   sprintf(diagMsg, "Number in merged lists: %d\n", editCanvas->numInMergedLists);
  1166.   PrintDiagnostics(diagMsg);
  1167.   
  1168.   sprintf(listEntry, "%5d.  %-26.22s%3d", origLines+1,            /* Display new edit on source edit list */
  1169.       srcEditLabel[origLines], srcEditDur[origLines]);
  1170.   xv_set (vcrDub_window1->dubScrollList,
  1171.       PANEL_LIST_INSERT, origLines,
  1172.       PANEL_LIST_STRING, origLines, listEntry,
  1173.       PANEL_LIST_FONT, origLines, font,
  1174.       NULL);
  1175.   
  1176.   origLines ++;      
  1177.   
  1178.   DrawLinkedList(editCanvas->listHead, No);
  1179.   xv_set(vcrDub_window1->dubMergeButton, PANEL_INACTIVE, TRUE, NULL);
  1180.   xv_set(vcrDub_window1->dubMergeLabel, PANEL_VALUE, "Merge - No label", NULL);
  1181.   xv_set(vcrDub_window1->dubMergeLabel, PANEL_INACTIVE, TRUE, NULL);
  1182.   
  1183.   notSaved = 1;
  1184. }
  1185.  
  1186.  
  1187. /*
  1188.  * Notify callback function for `dubDelButton'.
  1189.  */
  1190. void
  1191.   DubDelete(item, event)
  1192. Panel_item    item;
  1193. Event        *event;
  1194. {
  1195.   EditLink* toDel;
  1196.   
  1197.   toDel = GetEdit(editCanvas->firstSelected -1);
  1198.   EditDelete(toDel);
  1199.   
  1200.   notSaved = 1;
  1201.   editCanvas->firstSelected = -1;                    /* Deselect edit */
  1202.   EditOpInactive();
  1203.   DrawLinkedList(editCanvas->listHead, No);
  1204. }
  1205.  
  1206.  
  1207. /* Switches the position of 2 edits next to each other in linked list */
  1208. void
  1209.   SwitchConsec(top, bottom)
  1210. EditLink* top;
  1211. EditLink* bottom;
  1212. {
  1213.   if (top->prevEdit == NULL)
  1214.     editCanvas->listHead = bottom;
  1215.   else
  1216.     top->prevEdit->nextEdit = bottom;
  1217.   
  1218.   if (bottom->nextEdit)
  1219.     bottom->nextEdit->prevEdit = top;
  1220.   else
  1221.     editCanvas->listTail = top;
  1222.   
  1223.   bottom->prevEdit = top->prevEdit;
  1224.   top->nextEdit = bottom->nextEdit;
  1225.   bottom->nextEdit = top;
  1226.   top->prevEdit = bottom;
  1227. }
  1228.  
  1229.  
  1230. /* Switches the position of 2 edits not next to each other in linked list */
  1231. void
  1232.   SwitchNonConsec(top, bottom)
  1233. EditLink* top;
  1234. EditLink* bottom;
  1235. {
  1236.   EditLink* tmp1;
  1237.   EditLink* tmp2;
  1238.   
  1239.   if (top->prevEdit == NULL)
  1240.     editCanvas->listHead = bottom;
  1241.   else
  1242.     top->prevEdit->nextEdit = bottom;
  1243.   
  1244.   if (top->nextEdit)
  1245.     top->nextEdit->prevEdit = bottom;
  1246.   
  1247.   if (bottom->prevEdit)
  1248.     bottom->prevEdit->nextEdit = top;
  1249.   
  1250.   if (bottom->nextEdit)
  1251.     bottom->nextEdit->prevEdit = top;
  1252.   else
  1253.     editCanvas->listTail = top;
  1254.   
  1255.   tmp1 = bottom->prevEdit;
  1256.   tmp2 = bottom->nextEdit;
  1257.   bottom->prevEdit = top->prevEdit;
  1258.   top->prevEdit = tmp1;
  1259.   bottom->nextEdit = top->nextEdit;
  1260.   top->nextEdit = tmp2;
  1261.   
  1262. }
  1263.  
  1264.  
  1265. void RearrangeEdit(canvas, replacedEditNum)
  1266.      CanvasData* canvas;
  1267.      int replacedEditNum;                        /* from 1 to n */
  1268. {
  1269.   EditLink* movingEdit;
  1270.   EditLink* replacedEdit;
  1271.   
  1272.   if (replacedEditNum != canvas->firstSelected)                /* Not moving to same place */
  1273.   {
  1274.     replacedEdit = GetEdit(replacedEditNum-1);                /* Get the edits involved in shift */
  1275.     movingEdit = GetEdit(canvas->firstSelected - 1);
  1276.     
  1277.     if (replacedEdit->nextEdit == movingEdit)                /* Two edits are right next to each other */
  1278.       SwitchConsec(replacedEdit, movingEdit);
  1279.     else if (movingEdit->nextEdit == replacedEdit)
  1280.       SwitchConsec(movingEdit, replacedEdit);
  1281.     else if (replacedEditNum > canvas->firstSelected)            /* replaced is below original */
  1282.       SwitchNonConsec(movingEdit, replacedEdit);
  1283.     else if (replacedEditNum < canvas->firstSelected)            /* replaced is above original */
  1284.       SwitchNonConsec(replacedEdit, movingEdit);
  1285.   }  
  1286.   canvas->firstSelected = replacedEditNum;
  1287.   EditOpActive(movingEdit->audioDub);
  1288.   DrawLinkedList(editCanvas->listHead, No);
  1289.   
  1290. }
  1291.  
  1292. /*
  1293.  * Event callback function for `dubEditCanvas'.
  1294.  */
  1295. Notify_value
  1296.   EditEventHandler(win, event, arg, type)
  1297. Xv_window    win;
  1298. Event        *event;
  1299. Notify_arg    arg;
  1300. Notify_event_type type;
  1301. {
  1302.   int tempChosenEdit;
  1303.   int replacedEdit;
  1304.   static int leftButtonWasDown;
  1305.   static int prevEditY;
  1306.   static int numRightSelected;
  1307.   char label[40];
  1308.   EditLink* current;
  1309.   EditLink* prev;
  1310.   
  1311.   numRightSelected = 0;
  1312.   if (event_is_down(event) && editCanvas->numInLinkedList >0)        /* Something got selected */
  1313.   {
  1314.     tempChosenEdit = event_y(event) / (EditHeight + EditGap);        /* Get the relative position of the mouse click, 
  1315.                                        with respect to the height and spacing of the icons */
  1316.     if (tempChosenEdit && (tempChosenEdit <= editCanvas->numInLinkedList)) 
  1317.     {                                    /* An application is now chosen */
  1318.       current = GetEdit(tempChosenEdit-1);
  1319.       if (event_id(event) == MS_LEFT)                    /* Left mouse button was clicked */
  1320.       {
  1321.     prevEditY = event_y(event) - (EditHeight)/2;            /* Only left mouse dragging is permitted */
  1322.     
  1323.     leftButtonWasDown = 1;
  1324.     if (editCanvas->firstSelected != tempChosenEdit) 
  1325.     {
  1326.       if (editCanvas->firstSelected > 0)                /* Redraw the previously chosen edit so that 
  1327.                                        it is unselected */
  1328.       {
  1329.         prev = GetEdit(editCanvas->firstSelected-1);
  1330.         prev->sMode = Unselected;
  1331.         sprintf(label, "%3d. %-23.22s", prev->origNum+1,
  1332.             srcEditLabel[prev->origNum]);
  1333.         DrawEdit(LeftMargin, editCanvas->firstSelected*(EditGap + EditHeight), 
  1334.              label, prev->audioDub, Unselected);                
  1335.       }
  1336.       sprintf(label, "%3d. %-23.22s", current->origNum+1,
  1337.           srcEditLabel[current->origNum]);
  1338.       DrawEdit(LeftMargin, tempChosenEdit*(EditGap + EditHeight), /* Redraw the current edit to first-selected */
  1339.            label, current->audioDub, Selected);    
  1340.       xv_set(vcrDub_window1->dubAudioStg, PANEL_VALUE, 
  1341.          (int) current->audioDub, NULL);
  1342.       
  1343.       editCanvas->firstSelected = tempChosenEdit;            
  1344.       EditOpActive(current->audioDub);
  1345.       if (current->sMode == Selected)                /* Used to be second-selected */
  1346.       {
  1347.         xv_set(vcrDub_window1->dubMergeButton, PANEL_INACTIVE, TRUE, NULL);
  1348.         xv_set(vcrDub_window1->dubMergeLabel, PANEL_VALUE, "Merge - No label", NULL);
  1349.         xv_set(vcrDub_window1->dubMergeLabel, PANEL_INACTIVE, TRUE, NULL);
  1350.       }
  1351.       else
  1352.         current->sMode = Selected;
  1353.     }
  1354.       }
  1355.       else if (event_id(event) == MS_RIGHT)
  1356.       {
  1357.     if (editCanvas->firstSelected != tempChosenEdit)        /* If selected with left button already, do nothing */
  1358.     {
  1359.       if (current->sMode == Selected)                /* Right mouse button allows deselection on 2nd click */
  1360.       {
  1361.         sprintf(label, "%3d. %-23.22s", current->origNum+1,
  1362.             srcEditLabel[current->origNum]);
  1363.         DrawEdit(LeftMargin, tempChosenEdit*(EditGap + EditHeight), 
  1364.              label, current->audioDub, Unselected);            
  1365.         current->sMode = Unselected;
  1366.         if (numRightSelected)
  1367.           numRightSelected--;
  1368.       }
  1369.       else                                /* Select it */
  1370.       {
  1371.         current->sMode = Selected;        
  1372.         sprintf(label, "%3d. %-23.22s", current->origNum+1,
  1373.             srcEditLabel[current->origNum]);
  1374.         DrawEdit(LeftMargin, tempChosenEdit*(EditGap + EditHeight), 
  1375.              label, current->audioDub, Selected);    
  1376.         numRightSelected--;
  1377.       }
  1378.       
  1379.       if ((editCanvas->firstSelected >0) && (numRightSelected)) /* First edit is also selected */
  1380.       {
  1381.         xv_set(vcrDub_window1->dubMergeButton, PANEL_INACTIVE, FALSE, NULL);
  1382.         xv_set(vcrDub_window1->dubMergeLabel, PANEL_INACTIVE, FALSE, NULL);
  1383.       }
  1384.       else
  1385.       {
  1386.         xv_set(vcrDub_window1->dubMergeButton, PANEL_INACTIVE, TRUE, NULL);
  1387.         xv_set(vcrDub_window1->dubMergeLabel, PANEL_VALUE, "Merge - No label", NULL);
  1388.         xv_set(vcrDub_window1->dubMergeLabel, PANEL_INACTIVE, TRUE, NULL);
  1389.       }
  1390.     }
  1391.       }
  1392.       else if (event_id(event) == LOC_DRAG && leftButtonWasDown)    /* Dragging */
  1393.       {
  1394.     if (leftButtonWasDown > 1) 
  1395.     {
  1396.       XDrawRectangle(editCanvas->display, editCanvas->drawable, editCanvas->gcXor, 
  1397.              LeftMargin, prevEditY,
  1398.              EditWidth, EditHeight);
  1399.     }
  1400.     leftButtonWasDown ++;
  1401.     prevEditY = event_y(event);
  1402.     if (prevEditY < 0)                        /* Set the lower and upper limits where the 
  1403.                                        'Edit box' can move */
  1404.       prevEditY = 0;
  1405.     else if (prevEditY > editCanvas->numInLinkedList * (EditHeight + EditGap)) 
  1406.       prevEditY = editCanvas->numInLinkedList * (EditHeight + EditGap);
  1407.     
  1408.     prevEditY -= EditHeight/2;
  1409.     XDrawRectangle(editCanvas->display, editCanvas->drawable, editCanvas->gcXor, 
  1410.                LeftMargin, prevEditY,
  1411.                EditWidth, EditHeight);
  1412.       }
  1413.     }
  1414.   }
  1415.   else if (event_is_up(event))                        /* Mouse up */
  1416.   {
  1417.     if (leftButtonWasDown > 1)                        /* Perform the following only if there had been dragging */
  1418.     {
  1419.       XDrawRectangle(editCanvas->display, editCanvas->drawable, editCanvas->gcXor, 
  1420.              LeftMargin, prevEditY,
  1421.              EditWidth, EditHeight);
  1422.       leftButtonWasDown = 0;
  1423.       replacedEdit = event_y(event) / (EditHeight + EditGap);       
  1424.       if (replacedEdit < 1) 
  1425.     replacedEdit = 1;
  1426.       else if (replacedEdit > editCanvas->numInLinkedList) 
  1427.     replacedEdit = editCanvas->numInLinkedList;
  1428.       
  1429.       if (replacedEdit != editCanvas->firstSelected) 
  1430.       {
  1431.     RearrangeEdit(editCanvas, replacedEdit);
  1432.     notSaved = 1;
  1433.       }
  1434.     }
  1435.   }
  1436.   return notify_next_event_func(win, (Notify_event) event, arg, type);
  1437. }
  1438.  
  1439.  
  1440. /*
  1441.  * Repaint callback function for `dubEditCanvas'.
  1442.  */
  1443. void
  1444.   EditRepaintHandler(canvas, paint_window, rects)
  1445. Canvas        canvas;
  1446. Xv_window    paint_window;
  1447. Rectlist    *rects;
  1448. {
  1449.   if (editCanvas->listHead)
  1450.     DrawLinkedList(editCanvas->listHead, No);
  1451. }
  1452.  
  1453.  
  1454. /*
  1455.  * Notify callback function for `playDeckDeviceStg'.
  1456.  * Set up play deck's video object.
  1457.  */
  1458. void
  1459.   SetPlayDevice(item, value, event)
  1460. Panel_item    item;
  1461. int        value;
  1462. Event        *event;
  1463. {
  1464.   int playPort;
  1465.   char deviceName[MaxNameLength];
  1466.   char playDev[10];
  1467.   
  1468.   playPort = xv_get(vcrDub_dubSetupWindow->playDeckStg, PANEL_VALUE);
  1469.   if (playPort)
  1470.     strcpy(playDev, "/dev/ttyb");
  1471.   else
  1472.     strcpy(playDev, "/dev/ttya");
  1473.   
  1474.   strcpy(deviceName, allDevices[value]);
  1475.   playVideo = DevInit(deviceName, playDev);
  1476.   DevStop(playVideo);
  1477.   DevSetDefaults(playVideo, 3, 0, 0, 0);    
  1478.   
  1479. }
  1480.  
  1481. /*
  1482.  * Notify callback function for `recDeckDeviceStg'.
  1483.  * Set up record deck's video object.
  1484.  */
  1485. void
  1486.   SetRecDevice(item, value, event)
  1487. Panel_item    item;
  1488. int        value;
  1489. Event        *event;
  1490. {
  1491.   int recPort;
  1492.   char deviceName[MaxNameLength];
  1493.   char recDev[10];
  1494.   
  1495.   recPort = xv_get(vcrDub_dubSetupWindow->recDeckStg, PANEL_VALUE);
  1496.   if (recPort)
  1497.     strcpy(recDev, "/dev/ttyb");
  1498.   else
  1499.     strcpy(recDev, "/dev/ttya"); 
  1500.   
  1501.   strcpy(deviceName, allDevices[value]);
  1502.   recVideo = DevInit(deviceName, recDev);
  1503.   DevStop(recVideo);
  1504.   DevSetDefaults(recVideo, 3, 0, 0, 0);    
  1505. }
  1506.  
  1507.  
  1508. /*
  1509.  * Notify callback function for `playDeckStg'.
  1510.  */
  1511. void
  1512.   SetPlayDeck(item, value, event)
  1513. Panel_item    item;
  1514. int        value;
  1515. Event        *event;
  1516. {
  1517.   if (value == 0)
  1518.     xv_set(vcrDub_dubSetupWindow->recDeckStg, PANEL_VALUE, 1, NULL);
  1519.   else
  1520.     xv_set(vcrDub_dubSetupWindow->recDeckStg, PANEL_VALUE, 0, NULL);
  1521. }
  1522.  
  1523. /*
  1524.  * Notify callback function for `recDeckStg'.
  1525.  */
  1526. void
  1527.   SetRecDeck(item, value, event)
  1528. Panel_item    item;
  1529. int        value;
  1530. Event        *event;
  1531. {
  1532.   if (value == 0)
  1533.     xv_set(vcrDub_dubSetupWindow->playDeckStg, PANEL_VALUE, 1, NULL);
  1534.   else
  1535.     xv_set(vcrDub_dubSetupWindow->playDeckStg, PANEL_VALUE, 0, NULL);
  1536. }
  1537.  
  1538.  
  1539. /* Set all functions inactive while dubbing */
  1540. void
  1541.   SetAppMute()
  1542. {
  1543.   xv_set(vcrDub_window1->dubDocButton, PANEL_INACTIVE, TRUE, NULL);
  1544.   xv_set(vcrDub_window1->dubAddButton, PANEL_INACTIVE, TRUE, NULL);
  1545.   xv_set(vcrDub_window1->dubMergeLabel, PANEL_VALUE, "Merge - No label", NULL);
  1546.   xv_set(vcrDub_window1->dubMergeButton, PANEL_INACTIVE, TRUE, NULL);
  1547.   xv_set(vcrDub_window1->dubDelButton, PANEL_INACTIVE, TRUE, NULL);
  1548.   xv_set(vcrDub_window1->dubAudioStg, PANEL_INACTIVE, TRUE, NULL);
  1549. }
  1550.  
  1551.  
  1552. /* Set all functions active after dubbing */
  1553. void
  1554.   SetAppActive()
  1555. {
  1556.   xv_set(vcrDub_window1->dubDocButton, PANEL_INACTIVE, FALSE, NULL);
  1557.   xv_set(vcrDub_window1->dubAddButton, PANEL_INACTIVE, FALSE, NULL);
  1558.   xv_set(vcrDub_window1->dubMergeButton, PANEL_INACTIVE, FALSE, NULL);
  1559.   xv_set(vcrDub_window1->dubDelButton, PANEL_INACTIVE, FALSE, NULL);
  1560.   xv_set(vcrDub_window1->dubAudioStg, PANEL_INACTIVE, FALSE, NULL);
  1561. }
  1562.  
  1563.  
  1564.  
  1565. char*
  1566.   Modify(time, duration)
  1567. char time[12];
  1568. int duration;                            /* in frames per second */
  1569. {
  1570.   char newAddress[12];
  1571.   int n;
  1572.   int hr;
  1573.   int min;
  1574.   int sec;
  1575.   int frame;
  1576.   
  1577.   n = ConvertToAddress(time) + duration;
  1578.   ConvertToTime(&hr, &min, &sec, &frame, n);
  1579.   
  1580.   sprintf(newAddress, "%.2d:%.2d:%.2d:%.2d", hr, min, sec, frame);
  1581.   return(newAddress);
  1582.   
  1583. }
  1584.  
  1585.  
  1586. void
  1587.   DubThisEdit(recordStart, playStart, playEnd, toDubAudio, editNum)
  1588. char recordStart[12];
  1589. char playStart[12];
  1590. char playEnd[12];
  1591. enum Boolean toDubAudio;
  1592. int editNum;
  1593. {
  1594.   static int rStart;
  1595.   int rEnd;
  1596.   int pStart;
  1597.   int pEnd;
  1598.   char status[50];                            /* String to describe status of dub */
  1599.   
  1600.   if (recordStart)
  1601.     rStart = ConvertToAddress(recordStart);
  1602.   pStart = ConvertToAddress(playStart);
  1603.   pEnd = ConvertToAddress(playEnd);
  1604.   rEnd = rStart + (pEnd - pStart);
  1605.   
  1606.   sprintf(status, "Searching to edit %d on play deck", editNum);    /* Do dubbing */
  1607.   xv_set(vcrDub_window1->dubStatusMsg, PANEL_VALUE, status, NULL);
  1608.   XFlush((Display*)xv_get(vcrDub_window1->window1, XV_DISPLAY));
  1609.   DevPlayFromTo(playVideo, pStart, pStart, FrameRate);            /* Search to beginning of segment on playback deck */
  1610.   
  1611.   if (toDubAudio == Yes)
  1612.     DevSetAudio(playVideo, 1);
  1613.   else
  1614.     DevSetAudio(playVideo, 0);
  1615.   
  1616.   if (recordStart)                            /* If NULL, continue from current position */
  1617.   {
  1618.     sprintf(status, "Searching on record deck (edit %d)", editNum);
  1619.     xv_set(vcrDub_window1->dubStatusMsg, PANEL_VALUE, status, NULL);
  1620.     XFlush((Display*)xv_get(vcrDub_window1->window1, XV_DISPLAY));
  1621.     DevPlayFromTo(recVideo, rStart, rStart, FrameRate);            /* Search to beginning of record point on record deck */
  1622.     DevRecordFromTo(recVideo, 0, 0, 0);                    /* Put record deck into Insert edit mode */
  1623.   }
  1624.   DevPlayFromTo(playVideo, NULL, pEnd, FrameRate);            /* Begin playing the segment on the playback deck */
  1625.   DevRecordFromTo(recVideo, 0, rEnd, 0);                /* Begin recording on the record deck */
  1626.   
  1627.   rStart = rEnd;                            /* In case of merged edit, we want next start address ...
  1628.                                        ... on record side to be current end address */
  1629.   sprintf(status, "Done with edit %d", editNum);
  1630.   xv_set(vcrDub_window1->dubStatusMsg, PANEL_VALUE, status, NULL);
  1631.   XFlush((Display*)xv_get(vcrDub_window1->window1, XV_DISPLAY));
  1632. }
  1633.  
  1634.  
  1635. /* Start dubbing.
  1636.  * Load linked list into edit list.
  1637.  * Dub edits using info in edit list.
  1638.  */
  1639. void
  1640.   StartDub()
  1641. {
  1642.   MergeEdit* current;                            /* Current merged edit portion */
  1643.   char playTape[MaxNameLength];                        /* Play tape header */
  1644.   char recTape[MaxNameLength];                        /* Play tape header */
  1645.   char newEditStart[MaxListSize][12];                    /* Array of edit start times for dubbed tape */
  1646.   char newEditEnd[MaxListSize][12];                    /* Array of edit end times for dubbed tape */
  1647.   int i;
  1648.   int tmphr; 
  1649.   int tmpmin; 
  1650.   int tmpsec;
  1651.   int tmpframe;
  1652.   int mergeEditDur;                            /* Duration for entire merged edit */
  1653.   int editInterval;                            /* Interval on new tape between edits, in frames per second */
  1654.   
  1655.   LoadEditList(editCanvas->listHead);                    /* Loads linked list info into edit list */
  1656.   xv_set(vcrDub_window1->dubEditListMsg, PANEL_VALUE, "Dubbed Edit List");
  1657.   XFlush((Display*)xv_get(vcrDub_window1->window1, XV_DISPLAY));
  1658.   
  1659.   sprintf(recTape, "NULL");
  1660.   sprintf(playTape, "NULL");
  1661.   
  1662.   editInterval = FrameRate *
  1663.     (int) xv_get(vcrDub_dubSetupWindow->intervalTxt, PANEL_VALUE) ;
  1664.   
  1665.   ConvertToTime(&tmphr, &tmpmin, &tmpsec, &tmpframe,
  1666.         FrameRate * xv_get(vcrDub_dubSetupWindow->startAddTxt, PANEL_VALUE));
  1667.   
  1668.   sprintf(newEditStart[0], "%.2d:%.2d:%.2d:%.2d",
  1669.       tmphr, tmpmin, tmpsec, tmpframe);
  1670.   
  1671.   for (i = 0; i< origLines; i++)
  1672.   {
  1673.     if (srcEditMergeEdit[i])                        /* This is a merged edit */
  1674.     {
  1675.       current = srcEditMergeEdit[i];
  1676.       DubThisEdit(newEditStart[i], current->startAddress,
  1677.           current->endAddress, Yes, i+1);
  1678.       mergeEditDur = (ConvertToAddress(current->endAddress) 
  1679.               - ConvertToAddress(current->startAddress));   /* In frames per second */
  1680.       current = current->nextMergeEdit;
  1681.       while (current)
  1682.       {
  1683.     DubThisEdit(NULL, current->startAddress,
  1684.             current->endAddress, srcEditAudioDub[i], i+1);  /* Continue from here */
  1685.     
  1686.     mergeEditDur += (ConvertToAddress(current->endAddress) 
  1687.              - ConvertToAddress(current->startAddress)); /* In frames per second */
  1688.     current = current->nextMergeEdit;
  1689.       }
  1690.       DevStop(recVideo);
  1691.       
  1692.       strcpy(newEditEnd[i], Modify(newEditStart[i], mergeEditDur));
  1693.       strcpy(newEditStart[i+1], Modify(newEditEnd[i], editInterval));
  1694.     }
  1695.     else                                /* This is a regular edit */
  1696.     {
  1697.       DubThisEdit(newEditStart[i], srcEditStart[i], srcEditEnd[i], srcEditAudioDub[i], i+1);
  1698.       if (srcEditAudioDub[i] == No)
  1699.     srcEditAudio[i] = 3;                        /* Audio is muted because not dubbed onto tape */
  1700.       strcpy(newEditEnd[i],
  1701.          Modify(newEditStart[i], 
  1702.             (ConvertToAddress(srcEditEnd[i])
  1703.              - ConvertToAddress(srcEditStart[i]))));
  1704.       strcpy(newEditStart[i+1], Modify(newEditEnd[i], editInterval));
  1705.     }
  1706.   }
  1707.   
  1708.   DevStop(recVideo);                            /* End of dubbing */
  1709.   DevStop(playVideo);
  1710.   for (i = 0; i< origLines; i++)                    /* Copy dub array times into source array */
  1711.   {
  1712.     strcpy(srcEditStart[i], newEditStart[i]);
  1713.     strcpy(srcEditEnd[i], newEditEnd[i]);
  1714.     srcEditMergeEdit[i] = NULL;                        /* Already merged, so no longer set */
  1715.   }
  1716.   editCanvas->numMerged = 0;
  1717.   editCanvas->numInMergedLists = 0;
  1718.   
  1719.   strncpy(tapeCode, recTape, 4);
  1720.   notSaved = 1;
  1721.   dubbing = 0;
  1722.   
  1723.   SetAppActive();
  1724.   SetUpLinkedList(&editCanvas->listHead, &editCanvas->listTail);    /* Set up new linked list */
  1725.   DrawLinkedList(editCanvas->listHead, No);
  1726.   
  1727.   Browse(NULL, BrowseSave, 1, "#VCR Edit Document#", "vcrDub");        /* Pop up OpenPanel, with id = 1 */
  1728. }                                    /* end function StartDubbing */
  1729.  
  1730.  
  1731. /*
  1732.  * Notify callback function for `dubSerialDoneButton'.
  1733.  */
  1734. void
  1735.   SerialDone(item, event)
  1736. Panel_item    item;
  1737. Event        *event;
  1738. {
  1739.   xv_set(vcrDub_dubSetupWindow->dubSetupWindow, FRAME_CMD_PUSHPIN_IN, FALSE, NULL);
  1740.   xv_set(vcrDub_dubSetupWindow->dubSetupWindow, XV_SHOW, FALSE, NULL);
  1741.   
  1742.   xv_set(vcrDub_window1->dubStatusMsg, PANEL_VALUE, "Initializing decks", NULL);
  1743.   dubbing = 1;
  1744.   SetAppMute();
  1745.   StartDub();
  1746. }
  1747.  
  1748.  
  1749. void
  1750.   InitGlobals()
  1751. {  
  1752.   srcEditSel = -1;
  1753.   origLines = 0;
  1754.   notSaved = 0;
  1755.   repeat = 0;
  1756.   dubbing = 0;
  1757.   hitQuit = 0;
  1758.   playVideo = NULL;
  1759.   recVideo = NULL;
  1760.   
  1761. }
  1762.  
  1763.  
  1764.  
  1765. void
  1766.   InitCanvas(dataPtr)
  1767. CanvasData* dataPtr;
  1768. {
  1769.   dataPtr->paintWindow = canvas_paint_window(vcrDub_window1->dubEditCanvas);
  1770.   dataPtr->drawable = (Window) xv_get(dataPtr->paintWindow, XV_XID);
  1771.   dataPtr->display = (Display*) xv_get(vcrDub_window1->dubEditCanvas, XV_DISPLAY);
  1772.   
  1773.   dataPtr->gc = XCreateGC(dataPtr->display, dataPtr->drawable, 0, 0); /* GC stuff */
  1774.   XSetFont(dataPtr->display, dataPtr->gc, XLoadFont(dataPtr->display, "6x13"));
  1775.   XSetLineAttributes(dataPtr->display, dataPtr->gc, 1, LineSolid, CapRound, JoinRound);
  1776.   
  1777.   dataPtr->gcXor = XCreateGC(dataPtr->display, dataPtr->drawable, 0, 0); 
  1778.   XSetFunction(dataPtr->display, dataPtr->gcXor, GXxor);
  1779.   
  1780.   dataPtr->cms = xv_create(NULL, CMS, 
  1781.                CMS_SIZE, NumColors, 
  1782.                CMS_TYPE, XV_STATIC_CMS, 
  1783.                CMS_COLORS, myColors,
  1784.                NULL);
  1785.   
  1786.   xv_set(vcrDub_window1->dubEditCanvas,
  1787.      CANVAS_HEIGHT, 1800,
  1788.      WIN_CMS, dataPtr->cms,
  1789.      CANVAS_AUTO_SHRINK, FALSE,
  1790.      CANVAS_AUTO_EXPAND, TRUE, 
  1791.      NULL);
  1792.   
  1793.   dataPtr->pixelTable = (unsigned long*) xv_get(dataPtr->cms, CMS_INDEX_TABLE);
  1794.   
  1795.   audioImage = XCreateBitmapFromData(dataPtr->display, dataPtr->drawable, 
  1796.                      audioBitmap_bits, audioBitmap_width, audioBitmap_height);
  1797.   
  1798.   XSetForeground(dataPtr->display, dataPtr->gcXor, 
  1799.          dataPtr->pixelTable[Grey92]^dataPtr->pixelTable[Black]);
  1800.   
  1801.   dataPtr->firstSelected = -1;                        /* Nothing is initially selected */
  1802.   dataPtr->listHead = NULL;
  1803.   dataPtr->listTail = NULL;
  1804.   dataPtr->numInLinkedList = 0;
  1805.   dataPtr->numInMergedLists = 0;
  1806.   dataPtr->numMerged = 0;
  1807.   
  1808. }
  1809.  
  1810.  
  1811. /*
  1812.  * Notify callback function for `removeInfoWindowButton'.
  1813.  */
  1814. void
  1815.   RemoveInfoWindow(Panel_item item, Event *event)
  1816. {
  1817.   xv_set(vcrDub_infoPopup->infoPopup, FRAME_CMD_PUSHPIN_IN, FALSE, NULL);
  1818.   xv_set(vcrDub_infoPopup->infoPopup, XV_SHOW, FALSE, NULL);
  1819.   
  1820.   /* gxv_start_connections DO NOT EDIT THIS SECTION */
  1821.   
  1822.   /* gxv_end_connections */
  1823. }
  1824.  
  1825.  
  1826. /*
  1827.  * Menu handler for `DocMenu (About vcrDub...)'.
  1828.  */
  1829. Menu_item
  1830.   ShowInfoPanel(Menu_item item, Menu_generate op)
  1831. {
  1832.   switch (op)
  1833.   {
  1834.    case MENU_DISPLAY:
  1835.     break;
  1836.     
  1837.    case MENU_DISPLAY_DONE:
  1838.     break;
  1839.     
  1840.    case MENU_NOTIFY:
  1841.     xv_set(vcrDub_infoPopup->infoPopup, FRAME_CMD_PUSHPIN_IN, TRUE, NULL);
  1842.     xv_set(vcrDub_infoPopup->infoPopup, XV_SHOW, TRUE, NULL);
  1843.     
  1844.     /* gxv_start_connections DO NOT EDIT THIS SECTION */
  1845.     
  1846.     /* gxv_end_connections */
  1847.     
  1848.     break;
  1849.     
  1850.    case MENU_NOTIFY_DONE:
  1851.     break;
  1852.   }
  1853.   return item;
  1854. }
  1855.  
  1856.  
  1857. #ifdef MAIN
  1858.  
  1859. /*
  1860.  * Instance XV_KEY_DATA key.  An instance is a set of related
  1861.  * user interface objects.  A pointer to an object's instance
  1862.  * is stored under this key in every object.  This must be a
  1863.  * global variable.
  1864.  */
  1865. Attr_attribute    INSTANCE;
  1866.  
  1867. void
  1868.   main(argc, argv)
  1869. int        argc;
  1870. char        **argv;
  1871. {
  1872.   
  1873.   Rect  tempRect;
  1874.   char msg[MaxPathLength+20];
  1875.   int i;
  1876.   
  1877.   startFilename = NULL;                            /* Command line parsing */
  1878.   CheckOptions(argc, argv);
  1879.   xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, 0);            /* Initialize XView. */
  1880.   INSTANCE = xv_unique_key();
  1881.   
  1882.  
  1883.   vcrDub_window1 = vcrDub_window1_objects_initialize(NULL, NULL);   /* Initialize user interface components. */
  1884.   vcrDub_dubSetupWindow =
  1885.     vcrDub_dubSetupWindow_objects_initialize(NULL, vcrDub_window1->window1);
  1886.   vcrDub_infoPopup =
  1887.     vcrDub_infoPopup_objects_initialize(NULL, vcrDub_window1->window1);
  1888.   
  1889.   frame_get_rect(vcrDub_window1->window1,&tempRect);            /* Get the size of the top-level window */
  1890.   tempRect.r_top = 250;
  1891.   tempRect.r_left = 200;
  1892.   frame_set_rect(vcrDub_window1->window1,&tempRect);            /* Set the position of the top-level window */
  1893.   
  1894.   frame_get_rect(vcrDub_infoPopup->infoPopup,&tempRect);        /* Get the size of the info popup window */
  1895.   tempRect.r_top = 100;
  1896.   tempRect.r_left = 330;
  1897.   frame_set_rect(vcrDub_infoPopup->infoPopup,&tempRect);        /* Set the position of the info popup window */
  1898.  
  1899.   xv_set(vcrDub_window1->dubStatusMsg, PANEL_VALUE, " ", NULL);        /* Initialize window elements */
  1900.   xv_set(vcrDub_dubSetupWindow->playDeckStg, PANEL_VALUE, 1, NULL);
  1901.   xv_set(vcrDub_dubSetupWindow->recDeckStg, PANEL_VALUE, 0, NULL);
  1902.   xv_set(vcrDub_dubSetupWindow->startAddTxt, PANEL_VALUE, 10, NULL);
  1903.  
  1904.   frame_get_rect(vcrDub_dubSetupWindow->dubSetupWindow,&tempRect);  /* Get the size of the dub setup window */
  1905.   tempRect.r_top = 250;
  1906.   tempRect.r_left = 665;
  1907.   frame_set_rect(vcrDub_dubSetupWindow->dubSetupWindow,&tempRect);  /* Set the position of the dub setup window */
  1908.  
  1909.   xv_set(vcrDub_window1->dubAddButton, PANEL_INACTIVE, TRUE, NULL);
  1910.   xv_set(vcrDub_window1->dubMergeButton, PANEL_INACTIVE, TRUE, NULL);
  1911.   xv_set(vcrDub_window1->dubMergeLabel, PANEL_VALUE, "Merge - No Label", NULL);
  1912.   xv_set(vcrDub_window1->dubMergeLabel, PANEL_INACTIVE, TRUE, NULL);
  1913.   xv_set(vcrDub_window1->dubDelButton, PANEL_INACTIVE, TRUE, NULL);
  1914.   xv_set(vcrDub_window1->dubAudioStg, PANEL_INACTIVE, TRUE, NULL);
  1915.   xv_set(vcrDub_window1->dubAudioStg, PANEL_VALUE, 1, NULL);
  1916.   
  1917.   font = (Xv_font *)  xv_find(vcrDub_window1->window1, FONT,        /* Set font for panel list */
  1918.                   FONT_FAMILY, FONT_FAMILY_LUCIDA_FIXEDWIDTH,
  1919.                   FONT_STYLE,  FONT_STYLE_NORMAL,
  1920.                   FONT_SIZE, 12,
  1921.                   NULL);
  1922.   
  1923.   InitGlobals();                            /* Initialize global variables */
  1924.   editCanvas = (CanvasData*) malloc(sizeof(CanvasData));        /* Pointer to editCanvas data */
  1925.   InitCanvas(editCanvas);                        /* Initialize canvas variables */
  1926.   
  1927.   xv_set(vcrDub_dubSetupWindow->playDeckDeviceStg,            /* Initialize choices to devices supported */
  1928.      PANEL_NCHOICES, numDevices, NULL);
  1929.   xv_set(vcrDub_dubSetupWindow->recDeckDeviceStg, 
  1930.      PANEL_NCHOICES, numDevices, NULL);
  1931.   
  1932.   for (i=0; i < numDevices; i++)
  1933.   {
  1934.     xv_set(vcrDub_dubSetupWindow->playDeckDeviceStg,
  1935.        PANEL_CHOICE_STRING, i, allDevices[i], 
  1936.        NULL);
  1937.     xv_set(vcrDub_dubSetupWindow->recDeckDeviceStg,
  1938.        PANEL_CHOICE_STRING, i, allDevices[i], 
  1939.        NULL);
  1940.   }
  1941.   
  1942.   CreateBrowse(OpenHandler, SaveHandler, 
  1943.            vcrDub_window1->window1);                /* Set up Open Panel */
  1944.   
  1945.   if (startFilename)                            /* Set filename at start-up if included */
  1946.   {                                    /* as part of command line */
  1947.     sprintf(msg, "Current document: %s", startFilename);
  1948.     xv_set(vcrDub_window1->dubStatusMsg,                    
  1949.        PANEL_LABEL_STRING, msg, 
  1950.        NULL);
  1951.     Browse(startFilename, BrowseCheckOpen, NULL, "#VCR Edit Document", "vcrDub");
  1952.   }
  1953.   else
  1954.     xv_set(vcrDub_window1->dubStatusMsg,                    
  1955.        PANEL_LABEL_STRING, "No document loaded",
  1956.        NULL);
  1957.   
  1958.   xv_main_loop(vcrDub_window1->window1);                /* Turn control over to XView. */
  1959.   if (!hitQuit)
  1960.     DubQuit(NULL, NULL);
  1961.   exit(0);
  1962. }                                    /* end function main */
  1963.  
  1964. #endif
  1965.  
  1966.